package site.teamo.biu.net.server.controller;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.IdUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;
import site.teamo.biu.net.common.exception.BiuNetBusinessException;
import site.teamo.biu.net.common.report.ReportRequest;
import site.teamo.biu.net.common.report.ReportResponse;
import site.teamo.biu.net.common.util.HostPort;
import site.teamo.biu.net.common.util.URLUtil;
import site.teamo.biu.net.common.web.constant.ResponseCode;
import site.teamo.biu.net.common.web.mapper.SystemConfigMapper;
import site.teamo.biu.net.server.configuration.ServerConfiguration;
import site.teamo.biu.net.server.controller.model.client_management.QueryClientListResponse;
import site.teamo.biu.net.server.pojo.dto.ClientDTO;
import site.teamo.biu.net.server.service.ClientManagementService;
import site.teamo.biu.tool.core.model.BiuJSONResult;
import site.teamo.biu.tool.core.util.BiuJSONResultUtils;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * @author haocongshun
 * @date 2023/03/06 15:22:51
 */
@Tag(name = "客户端管理")
@RestController
@RequestMapping("/api/client-management")
public class ClientManagementController {

    private final Cache<String, String> accessKeys = CacheUtil.newTimedCache(300000);

    @Resource(name = "clientManagementServiceImpl")
    private ClientManagementService clientManagementService;

    @Resource
    private SystemConfigMapper systemConfigMapper;

    @GetMapping("/generate-access-url")
    public BiuJSONResult<String> generateAccessUrl(@RequestParam String name, HttpServletRequest request) {
        String query = URLUtil.buildQuery(MapUtil.of("key", buildAccessKey(name)), Charset.defaultCharset());
        return BiuJSONResultUtils.ok(URLUtil.getBaseURL(request) + "/api/client-management/access?" + query);
    }

    @GetMapping("/access")
    public BiuJSONResult<Map<String, String>> access(@RequestParam String key, @RequestParam String id, HttpServletRequest request) {
        String token = clientManagementService.createClient(id, verifyAccessKey(key));
        String url = URLUtil.getBaseURL(request);
        String reportUrl = url + "/api/client-management/report?id=" + id;
        return BiuJSONResultUtils.ok(Map.of("url", reportUrl, "token", token));
    }

    @Operation(summary = "查询客户端列表")
    @GetMapping("/query-client-list")
    public BiuJSONResult<QueryClientListResponse> queryClientList() {
        List<ClientDTO> clientDTOS = clientManagementService.queryClientList();
        return BiuJSONResultUtils.ok(new QueryClientListResponse(clientDTOS));
    }

    @Operation(summary = "删除客户端")
    @PostMapping("/delete-client/{clientId}")
    public BiuJSONResult<Boolean> deleteClient(@PathVariable(name = "clientId") String clientId) {
        return BiuJSONResultUtils.ok(clientManagementService.deleteClient(clientId));
    }

    @PostMapping("/report")
    public BiuJSONResult<ReportResponse> report(@RequestBody ReportRequest reportRequest, HttpServletRequest request) {
        ReportResponse response = new ReportResponse();
        int port = Integer.parseInt(ServerConfiguration.HTTP_HTTPS_PROXY_SERVICE_LISTEN_PORT.getContent(systemConfigMapper));
        response
                .setName(ServerConfiguration.SERVER_NAME.getContent(systemConfigMapper))
                .setProxyServer(HostPort.of(request.getServerName(), port));
        return BiuJSONResultUtils.ok(response);
    }

    public String buildAccessKey(String name) {
        String uuid = IdUtil.randomUUID();
        String key = HexUtil.encodeHexStr(uuid);
        accessKeys.put(uuid, name);
        return key;
    }

    public String verifyAccessKey(String key) {
        String decodeKey = HexUtil.decodeHexStr(key);
        if (accessKeys.containsKey(decodeKey)) {
            String name = accessKeys.get(decodeKey);
            accessKeys.remove(decodeKey);
            return name;
        } else {
            throw new BiuNetBusinessException(ResponseCode.BUSINESS_ERROR, "接入key失效");
        }
    }

}
